package game 
{
	import net.flashpunk.graphics.Tilemap;
	import net.flashpunk.masks.Grid;
	import net.flashpunk.World;
	import net.flashpunk.Entity;
	import net.flashpunk.FP;
	import net.flashpunk.graphics.Image;
	import utils.KeyCombo;
	
	import game.Camera;
	import game.Background;
	import game.GridTile;
	
	/**
	 * ...
	 * @author Matt Hofmann
	 */
	public class Level extends World 
	{
		
		[Embed(source = "../../levels/narutoTest1.oel", mimeType = "application/octet-stream")]
		public static const LEVEL1:Class;
		
		[Embed(source = "../../levels/narutoTest2.oel", mimeType = "application/octet-stream")]
		public static const LEVEL2:Class;
		
		[Embed(source = "../../levels/narutoTest3.oel", mimeType = "application/octet-stream")]
		public static const LEVEL3:Class;
		
		[Embed(source = "../../levels/narutoTest4.oel", mimeType = "application/octet-stream")]
		public static const LEVEL4:Class;
		
		protected var _map:Entity;
		protected var _player:Player;
		
		protected var _mapGrid:Grid;
		protected var _mapData:Class;
		protected var _mapImage:Image;
		protected var _mapWidth:uint;
		protected var _mapHeight:uint;
		
		public static var gameCamera:Camera = new Camera;
		
		public function Level(levelchoice:Class) 
		{	
			_mapData = levelchoice;
			
			// LEVEL1 is grid data, LEVEL2 is tile data!!!
			if (levelchoice == LEVEL1) {
				loadMap();
			}
			else if (levelchoice == LEVEL4) {
				loadLayeredTiles();
			}
			else {
				loadTiles();
			}
			
			// Set the camera's starting position
			gameCamera.setMapSize(_mapWidth, _mapHeight);
			gameCamera.adjustToPlayer(_player);
		}
		
		/** Called when World is switch to, and set to the currently active world. */
		override public function begin():void 
		{
			super.begin();
		}
		
		override public function update():void
		{
			// scroll along with the player
			if (_mapWidth && _player) {
				gameCamera.followPlayer(_player);
			}
			super.update();
		}
		
		/** Load map from Grid data **/
		protected function loadMap():void
		{
			// Load map data
			var mapXML:XML = FP.getXML(_mapData);
			
			// Create map grid
			_mapGrid = new Grid(uint(mapXML.@width), uint(mapXML.@height), 16, 16, 0, 0);
			_mapWidth = _mapGrid.width;
			_mapHeight = _mapGrid.height;
			
			// Load grid data from map data
			_mapGrid.loadFromString(String(mapXML.Grid), "", "\n");
			
			// Create image from map data, scale appropriately
			_mapImage = new Image(_mapGrid.data);
			_mapImage.scale = 16;

			// Create a map entity to render and check collision with.
			// Graphic = _mapImage
			// Mask (collisions) = _mapGrid
			_map = new Entity(0, 0, _mapImage, _mapGrid);
			
			// Set map collision type as 'wall' so that collision checking works
			_map.type = 'wall';			
		
			// Finally, add map entity (image and mask/hitboxes) to world
			add(_map);
			
			// Create a player at player start
			_player = new Player(uint(mapXML.Characters.PlayerStart.@x), uint(mapXML.Characters.PlayerStart.@y));
			add(_player);
		}
		
		/** Load map from Tileset Data **/
		protected function loadTiles():void 
		{
			// Load map data
			var mapXML:XML = FP.getXML(_mapData);
			
			// Track width/height of map
			_mapWidth = uint(mapXML.@width);
			_mapHeight = uint(mapXML.@height);
			
			// Loop through Grid.tile entries
			// These all have tileset IDs, but for now, assume they are all Walls
			// Create walls and add to world
			for each (var o:XML in mapXML.Grid.tile) {
				// Important to scale x/y based on tile size (XML data is grid position, not x/y position)
				var w:Wall = new Wall(uint(o.@x) * 16, uint(o.@y) * 16);
				
				// Wall class handles graphic, hitbox, and hit type; so just add it
				add(w);
			}
	
			// Create a player at player start; add to world
			_player = new Player(uint(mapXML.Characters.PlayerStart.@x), uint(mapXML.Characters.PlayerStart.@y));
			add(_player);
		}
		
		/** Load map from Tileset Data, with layers **/
		protected function loadLayeredTiles():void 
		{
			// Load map data
			var mapXML:XML = FP.getXML(_mapData);
			
			// Track width/height of map
			_mapWidth = uint(mapXML.@width);
			_mapHeight = uint(mapXML.@height);
			
			// The Images are either normal Image or Tilemaps
			// The Mask is a grid
			var midgroundImage:Tilemap = new Tilemap(GridTile.FOREST, 96 * 22, 96 * 11, 96, 96);	
			var foregroundImage:Tilemap = new Tilemap(GridTile.FOREST, 96 * 22, 96 * 11, 96, 96);	
			var foregroundMask:Grid = new Grid(_mapWidth, _mapHeight, 96, 96, 0, 40);
			
			// Add background
			add(new Entity(0, 0, new Background(Background.typeForest)));

			// Loop through midground tiles
			var o:XML;
			for each (o in mapXML.MG.tile) {
				midgroundImage.setTile(uint(o.@x), uint(o.@y), uint(o.@id));
			}
			// Loop thru foreground tiles
			for each (o in mapXML.FG.tile) {
				foregroundImage.setTile(uint(o.@x), uint(o.@y), uint(o.@id));
				foregroundMask.setTile(uint(o.@x), uint(o.@y), true);
			}
			
			var midground:Entity = new Entity(0, 0, midgroundImage);
			var foreground:Entity = new Entity(0, 0, foregroundImage, foregroundMask);
			foreground.type = 'wall';
			
			add(midground);
			add(foreground);
			
			//graphic = _tilemap = new Tilemap(TILESET, FP.screen.width, FP.screen.height, 20, 20);
			//mask = _grid = new Grid(FP.screen.width, FP.screen.height, 20, 20, 0, 0);		
	
			// Create a player at player start; add to world
			_player = new Player(uint(mapXML.Characters.PlayerStart.@x), uint(mapXML.Characters.PlayerStart.@y));
			add(_player);
		}
	}

}